#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

// V1版本的基于信号处理子进程存在无法处理多个子进程问题
// 如果在父进程执行其中一个子进程信号的处理时,有多个子进程发送SIGCHLD信号呢?
// 导致子进程无法全部被回收

void handle(int signo)
{
    // 捕捉到第一个子进程信号后就要不断循环等待子进程
    std::cout << "捕捉到一个SIGCHLD信号: " << signo << "我是:" << getpid() << std::endl;
    int status;
    do
    {
        int rid = waitpid(-1, &status, 0); // 阻塞模式
        if (rid > 0)
        {
            std::cout << "子进程退出, 子进程ID: " << rid << std::endl;
        }
        else if (rid < 0)
        {
            if (errno == ECHILD) // ECHILD表示没有子进程了,是waitpid设置error的值
            {                    // 避免将没有子进程的情况判断为错误
                std::cout << "所有子进程已退出" << std::endl; //而且执行信号处理的同时还能再缓存一个信号
            }                                                //也就是说必定会进来两次
            else                                             //避免第二次进入将没有进程回收的情况判定为错误
            {
                std::cerr << "waitpid错误" << std::endl;
            }
            break;
        }
    } while (true); // 持续等待，直到所有子进程退出
}

int main()
{
    ::signal(SIGCHLD, handle);
    std::cout << "我是父进程,Pid:" << getpid() << std::endl;
    sleep(1);
    for (int i = 1; i < 10; i++)
    {
        pid_t id = fork();
        if (id == 0)
        {
            std::cout << "我是子进程,Pid:" << getpid() << std::endl;
            sleep(i);
            exit(0);
        }
    }
    while (true)
    {
        sleep(1);
    }
    return 0;
}